package com.dwxt.cdms.service;

import com.dwxt.cdms.api.common.bean.SrcDataValue;
import com.dwxt.cdms.api.common.consts.ApiConsts;
import com.dwxt.cdms.api.common.utils.HdwDataCheckUtils;
import com.dwxt.cdms.api.common.utils.StringUtil;
import com.dwxt.cdms.constant.AiAoLeData;
import com.dwxt.cdms.dao.AiaoleDataMapper;
import com.dwxt.cdms.dao.BloodSugarMapper;
import com.dwxt.cdms.dao.BlutdruckMapper;
import com.dwxt.cdms.entity.AiaoleDataRecord;
import com.dwxt.cdms.entity.BloodSugar;
import com.dwxt.cdms.entity.Blutdruck;
import com.dwxt.cdms.entity.EquipmentCustom;
import com.dwxt.cdms.entity.vo.BlutdruckCustom;
import com.dwxt.common.constant.VariableConstants;
import com.dwxt.common.util.SnowIdUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.List;

/**
 * 爱奥乐
 *
 * @author Kuang.JiaZhuo
 * @date 2020-09-03 16:44
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AiAoLeDataService {

    private final BloodSugarMapper bloodSugarMapper;
    private final BlutdruckMapper blutdruckMapper;
    private final AiaoleDataMapper aiaoleDataMapper;
    private final HealthService healthService;
    private final EquipmentCustomService equipmentCustomService;

    private final static Logger logger = LoggerFactory.getLogger(AiAoLeDataService.class);

    /** 服务器IP地址 */
    @Value("${server.ip}")
    private String currServerIP;

    /**
     * @方法名：getBloodPressureAndBloodSugar
     * @描述： 解析(并新增)血压或血糖数据返回json
     * @作者： kjz
     * @日期： Created in 2020/9/3 16:46
     */
    @Transactional(rollbackFor = Exception.class)
    public Object getBloodPressureAndBloodSugar(String data) {

        Object object = new Object();

        // 校验数据合法性
        if (checkReceivedData(data)) {
            SrcDataValue srcDatavalue = new SrcDataValue(data);

            /** 只接收血糖、血压数据!!!!!!!!!!!!!!!! */
            String deviceType = srcDatavalue.getDeviceType();
            //血压
            String xyCode = ApiConsts.DataTypeEnum.BLPRESSURE.getCode();
            //血糖
            String xtCode = ApiConsts.DataTypeEnum.BLGLUCOSE.getCode();
            if(!(xyCode.equals(deviceType) || xtCode.equals(deviceType))) {
                return null;
            }

            int result = 0;

            if(xtCode.equals(deviceType)){
                /** 血糖 */
                BloodSugar bloodSugar = new BloodSugar(data)
                        .setId(SnowIdUtil.getInstance().nextId())
                        .setCreateTime(LocalDateTime.now())
                        .setDataType(AiAoLeData.DATA_TYPE_EXPLAIN_2);
                healthService.judgeIsNormalAndInsertRecord(bloodSugar);
                result = this.bloodSugarMapper.insert(bloodSugar);
                if(result>0){
                    object = bloodSugar;
                }
            }else if(xyCode.equals(deviceType))
            {
                /** 血压 */
                Blutdruck blutdruck = new Blutdruck(data)
                        .setId(SnowIdUtil.getInstance().nextId())
                        .setCreateTime(LocalDateTime.now())
                        .setDataType(AiAoLeData.DATA_TYPE_EXPLAIN_1);
                healthService.judgeIsNormalAndInsertRecord(blutdruck);
                //result = this.blutdruckMapper.insert(blutdruck);
                result = this.blutdruckMapper.insertSelective(blutdruck);
                if(result>0){
                    object = blutdruck;
                }
            }
        }
//        System.err.println(object);
        return object;
    }

    /**
     * @方法名：checkReceivedData
     * @描述： 校验上报数据的合法性
     * @作者： kjz
     * @日期： Created in 2020/9/3 17:06
     */
    public boolean checkReceivedData(String data) {

        if ((data != null) && ((data.length() == 85) || (data.length() == 87))) {

            if ((data.length() == 85)
                    && (HdwDataCheckUtils.isSumCheckCode(data))) {
                return true;
            }

            if ((data.length() == 87)
                    && (HdwDataCheckUtils.isSumCheckCode(data))
                    && (HdwDataCheckUtils.isCrc8Code(data))) {
                return true;
            }
        }

        return false;
    }

    /**
     * @方法名：selectBloodPressureByCondition
     * @描述： 按条件(带分页)查询血压列表
     * @作者： kjz
     * @日期： Created in 2020/9/4 11:09
     */
    public PageInfo<Blutdruck> selectBloodPressureByCondition(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum==null?1:pageNum, pageSize==null?10:pageSize);
        List<Blutdruck> list = this.blutdruckMapper.selectAll();
        PageInfo<Blutdruck> pageInfo = new PageInfo<>(list);
        return pageInfo;
    }

    /**
     * @方法名：selectBloodPressureById
     * @描述： 根据id查询血压数据详情
     * @作者： kjz
     * @日期： Created in 2020/9/4 11:24
     */
    public Blutdruck selectBloodPressureById(String id) {
        return this.blutdruckMapper.selectByPrimaryKey(id);
    }

    
    /**
     * @方法名：getBloodPressureAndBloodSugarBest
     * @描述： 解析(并新增)血压或血糖数据返回厂家的参数
     * @作者： kjz
     * @日期： Created in 2020/9/8 10:07
     */
    @Transactional(rollbackFor = Exception.class)
    public String getBloodPressureAndBloodSugarBest(HttpServletRequest request, HttpServletResponse response, String data) {
        logger.warn("爱奥乐数据："+data);
        if(null==data || "".equals(data.trim())){
           return null;
        }

        String aiaoleId = SnowIdUtil.getInstance().nextId();
        AiaoleDataRecord aiaoleDataRecord = new AiaoleDataRecord()
                .setId(aiaoleId)
                .setReceiveData(data)
                .setCreateTime(LocalDateTime.now());


        // 校验数据合法性
        if (checkReceivedData(data)) {

            SrcDataValue srcDatavalue = new SrcDataValue(data);
//			System.out.println(JSON.toJSON(srcDatavalue));

            // 只接收血糖、血压数据!!!!!!!!!!!!!!!!
            if(!(ApiConsts.DataTypeEnum.BLPRESSURE.getCode().equals(srcDatavalue.getDeviceType()) ||
                    ApiConsts.DataTypeEnum.BLGLUCOSE.getCode().equals(srcDatavalue.getDeviceType())))
            {
                return null;
            }

            // 处理上报的数据
            if(ApiConsts.DataTypeEnum.BLGLUCOSE.getCode().equals(srcDatavalue.getDeviceType())) {


                //新增数据记录
                aiaoleDataRecord.setType(AiAoLeData.AIAOLE_TYPE_1);
                aiaoleDataMapper.insert(aiaoleDataRecord);


                /** 血糖 */
                BloodSugar bloodSugar = new BloodSugar(data)
                        .setId(SnowIdUtil.getInstance().nextId())
                        .setCreateTime(LocalDateTime.now())
                        .setDataType(AiAoLeData.DATA_TYPE_EXPLAIN_2)
                        .setIsDelete(VariableConstants.STRING_CONSTANT_0);

                List<BloodSugar> bloodSugarList = bloodSugarMapper.selectBloodSugarBySerialNumberAndcheckTime(bloodSugar);

                if(bloodSugarList.size()==0){
                    //加入客户id
                    String deviceIdentity = bloodSugar.getSerialNumber();
                    EquipmentCustom equipmentCustom = equipmentCustomService.selectEquipmentCustomByDeviceIdentity(deviceIdentity);
                    if(equipmentCustom!=null && equipmentCustom.getCustomerId()!=null){
                        bloodSugar.setCustomerId(equipmentCustom.getCustomerId()).setAiaoleId(aiaoleId);
                        healthService.judgeIsNormalAndInsertRecord(bloodSugar);

                        this.bloodSugarMapper.insert(bloodSugar);
                    }
                }



            }else if(ApiConsts.DataTypeEnum.BLPRESSURE.getCode().equals(srcDatavalue.getDeviceType())) {

                //新增数据记录
                aiaoleDataRecord.setType(AiAoLeData.AIAOLE_TYPE_2);
                aiaoleDataMapper.insert(aiaoleDataRecord);

                /** 血压 */

                Blutdruck blutdruck = new Blutdruck(data)
                        .setId(SnowIdUtil.getInstance().nextId())
                        .setCreateTime(LocalDateTime.now())
                        .setDataType(AiAoLeData.DATA_TYPE_EXPLAIN_1)
                        .setIsDelete(VariableConstants.STRING_CONSTANT_0);

                List<Blutdruck> blutdruckList = blutdruckMapper.selectBlutdruckBySerialNumberAndcheckTime(blutdruck);
                int oldCount = blutdruckList.size();
                if(oldCount==0){

                    //加入客户id
                    String deviceIdentity = blutdruck.getSerialNumber();
                    EquipmentCustom equipmentCustom = equipmentCustomService.selectEquipmentCustomByDeviceIdentity(deviceIdentity);
                    if(equipmentCustom!=null && equipmentCustom.getCustomerId()!=null){
                        blutdruck.setCustomerId(equipmentCustom.getCustomerId()).setAiaoleId(aiaoleId);
                        healthService.judgeIsNormalAndInsertRecord(blutdruck);
                        //this.blutdruckMapper.insert(blutdruck);
                        this.blutdruckMapper.insertSelective(blutdruck);
                    }
                }
            }

            // 给血糖设备回复报文
            if (true) {
                StringBuilder rslt = new StringBuilder("+IP");
                rslt.append(getServerIp(request));
                rslt.append(getServerDate());
                rslt.append("OK");
                return rslt.toString();
            }
        }
        return null;
    }


    /**
     * 获取请求端ip地址
     *
     * @param request
     * @return
     */
    private String getServerIp(HttpServletRequest request) {

        String[] ips = StringUtil.toString(currServerIP).split("\\.");

        if ((null == ips) || (0 >= ips.length)) {
            return "";
        }

        String ports = StringUtils.leftPad(
                Integer.toHexString(request.getLocalPort()), 4, "0");

        StringBuilder ipsb = new StringBuilder();

        int sum = 0;

        for (int i = 0; i < ips.length; i++) {
            ipsb.append(StringUtils.leftPad(
                    Integer.toHexString(Integer.valueOf(ips[i]).intValue()), 2,
                    "0"));
            sum ^= Integer.valueOf(ips[i]).intValue();
        }

        sum ^= Integer.valueOf(ports.substring(2, 4), 16).intValue();
        ipsb.append(ports.substring(2, 4));
        sum ^= Integer.valueOf(ports.substring(0, 2), 16).intValue();
        ipsb.append(ports.substring(0, 2));
        ipsb.append(Integer.toHexString(sum));

        return ipsb.toString().toUpperCase();
    }

    /**
     * 获取服务器时间
     *
     * @return
     */
    private String getServerDate() {

        StringBuilder datasb = new StringBuilder();

        int sum = 0;

        Calendar cal = Calendar.getInstance();
        Integer year = Integer.valueOf(cal.get(1) % 100);
        datasb.append(StringUtils.leftPad(Integer.toHexString(year.intValue()),
                2, "0"));
        sum ^= year.intValue();

        Integer month = Integer.valueOf(cal.get(2) + 1);
        datasb.append(StringUtils.leftPad(
                Integer.toHexString(month.intValue()), 2, "0"));
        sum ^= month.intValue();

        Integer day = Integer.valueOf(cal.get(5));
        datasb.append(StringUtils.leftPad(Integer.toHexString(day.intValue()),
                2, "0"));
        sum ^= day.intValue();

        Integer hour = Integer.valueOf(cal.get(11));
        datasb.append(StringUtils.leftPad(Integer.toHexString(hour.intValue()),
                2, "0"));
        sum ^= hour.intValue();

        Integer minute = Integer.valueOf(cal.get(12));
        datasb.append(StringUtils.leftPad(
                Integer.toHexString(minute.intValue()), 2, "0"));
        sum ^= minute.intValue();

        datasb.append(StringUtils.leftPad(Integer.toHexString(sum), 2, "0"));

        return datasb.toString().toUpperCase();
    }

    /**
     * @方法名：deleteAiAoLeDataByCustomerIds
     * @描述： 根据客户id删除爱奥乐关联的客户健康数据
     * @作者： kjz
     * @日期： Created in 2020/9/12 16:21
     */
    @Transactional(rollbackFor = Exception.class)
    public int deleteAiAoLeDataByCustomerIds(Integer[] customerIds) {

        for (Integer id:customerIds) {
            if(id==4 || id==5){
                //测试数据暂不删除
                return 0;
            }
        }

        int result = 0;
        //血糖
        result+=bloodSugarMapper.deleteBloodSugarByCustomerIds(customerIds);
        //血压
        result+=blutdruckMapper.deleteBlutdruckByCustomerIds(customerIds);
        return result;
    }

    /**
     * @方法名：replaceBindingAiAoLeUser
     * @描述： 更换爱奥乐设备和用户的绑定
     * @作者： kjz
     * @日期： Created in 2020/9/16 17:48
     */
    @Transactional(rollbackFor = Exception.class)
    public int replaceBindingAiAoLeUser(Integer customerId, String serialNumber) {
        int result = 0;
        //血糖
        result+=bloodSugarMapper.replaceBindingAiAoLeUser(customerId,serialNumber);
        //血压
        result+=blutdruckMapper.replaceBindingAiAoLeUser(customerId,serialNumber);
        return result;
    }

    /**
     * @方法名：deleteWasteDataByWeek
     * @描述： 删除一周之前的爱奥乐废数据
     * @作者： kjz
     * @日期： Created in 2020/9/22 16:37
     */
    @Transactional(rollbackFor = Exception.class)
    public int deleteWasteDataByWeek() {
        int result = 0;
        List<AiaoleDataRecord> list = aiaoleDataMapper.selectAiaoleDataRecordByWeek();
        for (AiaoleDataRecord aiaole:list) {
            String type = aiaole.getType();
            String id = aiaole.getId();
            //血糖
            if(type.equals(AiAoLeData.AIAOLE_TYPE_1)){
                result+=aiaoleDataMapper.deleteAiAoLeDataByTypeGlu(id);
            }
            //血压
            if(type.equals(AiAoLeData.AIAOLE_TYPE_2)){
                result+=aiaoleDataMapper.deleteAiAoLeDataByTypeBp(id);
            }
        }
        return result;
    }

    public List<BlutdruckCustom> selectBloodPressureList(String customerId, Integer scope, Integer partId) {
        return blutdruckMapper.selectBloodPressureList(customerId,scope,partId);
    }
}
